﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using PMS.XCMG.Entity;
using PMS.XCMG.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PMS.XCMG.OpenApi.Controllers
{
    /// <summary>
    /// 中控数据接收接口
    /// </summary>
    [ApiController]
    public class CtrPmsController : ControllerBase
    {
        private IServiceProvider SvcProvider { get; set; }
        private IConfiguration Configuration { get; set; }

        public CtrPmsController(IServiceProvider svcProvider)
        {
            this.SvcProvider = svcProvider;
            this.Configuration = this.SvcProvider.GetRequiredService<IConfiguration>();
        }

        /// <summary>
        /// MES系统向中控PMS系统下发数据
        /// </summary>
        /// <param name="requestMsg">下发数据</param>
        /// <returns></returns>
        [HttpPost]
        [Route("[controller]/post")]
        public async Task<ReturnData> Post([FromBody] RequestMsgHeader requestMsg)
        {
            var rust = new ReturnData();
            try
            {
                switch (requestMsg.TaskType)
                {
                    case "10"://MES下发生产订单
                        rust = await SaveOrderAsync(requestMsg);
                        break;
                    case "11"://MES下发生产订单的BOM物料清单，中控以此生产预收单（中控内部使用）                        
                        break;
                    case "12"://MES反馈来料信息                       
                        break;
                    case "13"://MES取消未开始的生产订单                       
                        break;
                    default:
                        break;
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
                await Task.Delay(1000 * 1);
            }
            return rust;
        }

        /// <summary>
        /// 获取当前正在执行的计划编号
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<string> CurrentPlanAsync()
        {
            return await RedisHelper.GetAsync(RedisKeysHelper.Key_CurrentDeliveryPlanID);
        }

        /// <summary>
        /// 开始执行计划
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<string> StartPlanAsync(string id)
        {
            try
            {
                var currentId = await RedisHelper.GetAsync(RedisKeysHelper.Key_CurrentDeliveryPlanID);
                if (!string.IsNullOrWhiteSpace(currentId))
                {
                    using (var db = SvcProvider.GetRequiredService<GDbContext>())
                    {
                        var currentPlan = await db.Plan.AsQueryable().Where(p => p.Id == currentId).FirstOrDefaultAsync();
                        if (currentPlan.Status == PlanStatus.Executing)
                        {
                            if (currentPlan.DeliveryState == DeliveryStatus.Completed)
                            {
                                await DoStartPlanAsync(id, db);
                            }
                            else if (currentPlan.Status == PlanStatus.Completed || currentPlan.Status == PlanStatus.ManualEnd)
                            {
                                await DoStartPlanAsync(id, db);
                            }
                        }
                    }
                }
                else
                {
                    using (var db = SvcProvider.GetRequiredService<GDbContext>())
                    {
                        await DoStartPlanAsync(id, db);
                    }
                }

                return await RedisHelper.GetAsync(RedisKeysHelper.Key_CurrentDeliveryPlanID);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// 获取计划执行中的计划列表
        /// </summary>
        /// <param name="planId">计划编号</param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<List<Plan>> PlanListAsync()
        {
            List<Plan> result = new List<Plan>();
            try
            {
                using (var db = SvcProvider.GetRequiredService<GDbContext>())
                {
                    result = await db.Plan.AsQueryable().Where(p => p.Deleted == false && p.Status == PlanStatus.Issued
                    && (p.DeliveryState == DeliveryStatus.NotStarted || p.DeliveryState == DeliveryStatus.Executing)).ToListAsync();
                }
            }
            catch
            { }

            return result;
        }

        /// <summary>
        /// 获取计划的配送状态
        /// </summary>
        /// <param name="planId">计划编号</param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<PlanDeliveryState> DeliveryStateAsync(string planId)
        {
            PlanDeliveryState model = new PlanDeliveryState();

            try
            {
                using (var db = SvcProvider.GetRequiredService<GDbContext>())
                {
                    var entity = await db.Plan.AsQueryable()
                        .Include(i => i.Bom)
                        .ThenInclude(ti => ti.Spec)
                        .Where(p => p.Deleted == false && p.Id == planId)
                        .FirstOrDefaultAsync();

                    var prelist = await db.PlanPrepare
                        .AsQueryable()
                        .Where(p => p.Deleted == false && p.PlanId == planId)
                        .ToListAsync();

                    model.PlanId = entity.Id;
                    model.EleCode = entity.Bom.EleCode.ToString();
                    model.PlanDate = entity.PlanDate;
                    model.Quantity = entity.Quantity;
                    model.Code = entity.Code;
                    model.Name = entity.Name;
                    model.Count = entity.Count;
                    model.Status = entity.Status;
                    model.DeliveryState = entity.DeliveryState;
                    model.ManualEndCount = (from u in prelist select u.DeliveryCount).Max();
                    model.Prepares = (from u in prelist
                                      select new Prepare()
                                      {
                                          EleCode = u.EleCode,
                                          Count = u.Count,
                                          DeliveryCount = u.DeliveryCount,
                                          Id = u.Id,
                                          Name = u.Name,
                                          Quantity = ((int)u.Quantity),
                                          SpecName = u.SpecName
                                      }).ToList();
                }
            }
            catch
            { }

            return model;
        }

        /// <summary>
        /// 获取料位状态
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<Dictionary<string, string>> LocationStatusAsync(string code)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            try
            {
                var keys = RedisKeysHelper.Key_LocMeterStatus[code].ToArray();
                var values = await RedisHelper.MGetAsync(keys);
                for (var idx = 0; idx < keys.Length; idx++)
                {
                    result.Add(keys[idx].Replace("PMS.LocMeterStatus.", "").ToLower(), values[idx] == null ? "0" : values[idx]);
                }
            }
            catch
            { }

            return result;
        }

        /// <summary>
        /// 设置料位状态
        /// </summary>
        /// <param name="locCode">料位编码</param>
        /// <param name="status">料位状态</param>
        /// <param name="eleCode">料位物料编码</param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<string> ModifyLocationStatusAsync(string locCode, string status, string eleCode = "0")
        {
            var locMeterStatusAddress = RedisKeysHelper.PreLocMeterStatusAddress + locCode.ToUpper();
            var locMeterCodeAddress = RedisKeysHelper.PreLocMeterCodeAddress + locCode.ToUpper();

            await RedisHelper.SetAsync(locMeterStatusAddress, status);
            await RedisHelper.SetAsync(locMeterCodeAddress, eleCode);

            return await RedisHelper.GetAsync(locMeterStatusAddress);
        }

        /// <summary>
        /// 测试
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<RequestMsgHeader> HeaderAsync()
        {
            RequestMsgHeader header = new RequestMsgHeader();
            header.TaskId = Guid.NewGuid().ToString("n");
            header.TaskType = "10";
            header.Version = 1;
            header.Task = JsonConvert.SerializeObject(new OrderData()
            {
                BatchCode = DateTime.Now.ToString("yyyyMMdd_HHmmss"),
                OrderNo = DateTime.Now.ToString("yyyyMMdd_HHmmss"),
                ProductAlias = "2240-TG01108",
                ProductNo = "190007001",
                ProductName = "2240-TG01108",
                Quantity = 10,
                ScheduledStartDate = DateTime.Now.ToString("yyyy-MM-dd"),
                ScheduledCompleteDate = DateTime.Now.ToString("yyyy-MM-dd")
            });

            await Task.Delay(1);
            return header;
        }

        #region ----
        private static async Task DoStartPlanAsync(string id, GDbContext db)
        {
            var startPlan = await db.Plan.AsQueryable().Where(p => p.Id == id).FirstOrDefaultAsync();
            startPlan.DeliveryState = DeliveryStatus.Executing;
            if (startPlan.Status == PlanStatus.Issued)
            {
                startPlan.Status = PlanStatus.Executing;
            }
            db.Plan.Update(startPlan);
            await db.SaveChangesAsync();

            await RedisHelper.SetAsync(RedisKeysHelper.Key_CurrentDeliveryPlanID, id);
        }

        private async Task<ReturnData> SaveOrderAsync(RequestMsgHeader request)
        {
            var result = new ReturnData() { TaskId = request.TaskId, Code = "200", Version = request.Version.ToString() };

            try
            {
                OrderData model = JsonConvert.DeserializeObject<OrderData>(request.Task);

                using (var db = SvcProvider.GetRequiredService<GDbContext>())
                {
                    var spec = await db.MaterielSpec.AsQueryable().Where(p => p.MesCode == model.ProductNo && p.MaterielId == "10").FirstOrDefaultAsync();
                    var bom = await db.MaterialBom.AsQueryable().Where(p => p.SpecId == spec.Id && p.Deleted == false).FirstOrDefaultAsync();
                    var bomTree = await db.MaterialBomTree.AsQueryable()
                        .Include(i => i.Materiel)
                        .Include(i => i.Spec)
                        .Where(p => p.BomId == bom.Id && p.HasChild == false)
                        .ToListAsync();

                    if (spec != null && !string.IsNullOrWhiteSpace(spec.Id))
                    {
                        var plan = new Plan()
                        {
                            Id = Guid.NewGuid().ToString("n"),
                            BomId = bom.Id,
                            Code = model.ProductNo,
                            Name = model.ProductName,
                            Count = Convert.ToInt32(model.Quantity),
                            Quantity = 0,
                            PlanDate = model.ScheduledStartDate,
                            PlanDay = Convert.ToInt32(Convert.ToDateTime(model.ScheduledStartDate).ToString("yyyyMMdd")),
                            TeamTimeCode = null,
                            CreateTime = DateTime.Now,
                            CreateUserId = "1",
                            ModifyTime = DateTime.Now,
                            ModifyUserId = "1",
                            Deleted = false,
                            Status = PlanStatus.Issued
                        };
                        await db.Plan.AddAsync(plan);
                        List<PlanPrepare> prepareList = new List<PlanPrepare>();        //备料情况
                        List<Precollected> collectedList = new List<Precollected>();    //预收单
                        foreach (var item in bomTree)
                        {
                            await db.PlanPrepare.AddAsync(new PlanPrepare()
                            {
                                Id = Guid.NewGuid().ToString("n"),
                                PlanId = plan.Id,
                                BomTreeId = item.Id,
                                MaterielId = item.MaterialId,
                                //Code = item.Materiel.Code,
                                EleCode = item.EleCode,
                                Name = item.Materiel.Name,
                                SpecName = item.Spec.Name,
                                Count = Convert.ToInt32(item.Quantity * model.Quantity),
                                Quantity = 0,
                                DeliveryCount = 0,
                                CreateTime = DateTime.Now,
                                CreateUserId = "1",
                                ModifyTime = DateTime.Now,
                                ModifyUserId = "1",
                                Deleted = false
                            });

                            await db.Precollected.AddAsync(new Precollected()
                            {
                                Id = Guid.NewGuid().ToString("n"),
                                PlanId = plan.Id,
                                BomTreeId = item.Id,
                                EleCode = item.EleCode,
                                MaterielId = item.MaterialId,
                                MaterieCode = item.Materiel.Code,
                                MaterieName = item.Materiel.Name,
                                SpecId = item.SpecId,
                                SpecCode = item.Spec.Code,
                                SpecName = item.Spec.Name,
                                Quantity = Convert.ToInt32(item.Quantity * model.Quantity),
                                RealIncome = 0,
                                CreateTime = DateTime.Now,
                                CreateUserId = "1",
                                ModifyTime = DateTime.Now,
                                ModifyUserId = "1",
                                Deleted = false
                            });
                        }
                        db.SaveChanges();
                    }
                    else
                    {
                        result.Code = "404";
                        result.Msg = "不支持的产品类型";
                    }
                }
            }
            catch (Exception ex)
            {
                result.Code = "403";
                result.Msg = ex.Message;
            }

            return result;
        }
        #endregion

        /// <summary>
        /// 切换数字孪生视角
        /// </summary>
        /// <param name="locCode">料位编码</param>
        /// <param name="status">料位状态</param>
        /// <param name="eleCode">料位物料编码</param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<string> BoardView(int index)
        {
            using (var redis = new CSRedis.CSRedisClient("127.0.0.1:6379,defaultDatabase=8,poolsize=10,ssl=false,writeBuffer=10240"))
            {
                await redis.SetAsync("XgmgPmsBord_Unity_Station", index.ToString());
            }

            return "1";
        }
        /// <summary>
        /// 切换大屏菜单
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("[controller]/[action]")]
        public async Task<string> BoardMenu(int index)
        {
            using (var redis = new CSRedis.CSRedisClient("10.76.99.194:6379,defaultDatabase=0,poolsize=10,ssl=false,writeBuffer=10240"))
            {
                await redis.SetAsync("Board:MenuIndex", index.ToString());
            }
            return "1";
        }
    }
}
